// OpenGL.cpp
//
#include "OpenGL.h"

#include <iostream>
#include <sstream>
#include "MemCheck.h"

std::vector<std::string> OpenGL::glExtensions;
#ifdef _USE_GLEW_
//GLEWContext *OpenGL::globalGlewContext = NULL;
//GLEWContext *OpenGL::startingContext   = NULL;
#endif

//----------------------------------------------------------------------------------------------
bool OpenGL::glInitExtensions()
{
#ifdef _USE_GLEW_
	if( glewInit() == GLEW_OK )
	{
		std::string ext   ( (char *)glGetString(GL_EXTENSIONS) );
		std::string vendor( (char *)glGetString(GL_VENDOR) );
		std::string ver   ( (char *)glGetString(GL_VERSION) );
		std::string rend  ( (char *)glGetString(GL_RENDERER) );

		std::stringstream s(ext);
		

		OpenGL::glExtensions.clear();
		while( !s.eof() )
		{
			std::string str; s >> str;
		
			if( str.length()>0 )
				OpenGL::glExtensions.push_back( str );
		}

		std::cout << "Graphic adapter: " << vendor << std::endl;
		std::cout << "OpenGL renderer: " << rend   << std::endl;
		std::cout << "OpenGL Version:  " << ver    << std::endl << std::endl;
		
		if( glSupportMemoryQuery() )	std::cout << "Total Graphic Memory: " <<  (OpenGL::glGetTotalMemory() >> 10) << "MB" << std::endl;
		else							std::cout << "Total Graphic Memory: Unknown" << std::endl;


		//std::string file = resourcePath+std::string("/GLVersion.txt");
		//FILE *f = fopen(file.c_str(),"wt");
		//if(f)
		//{
		//	fprintf( f,"Graphic adapter:      %s\n",vendor.toLocal8Bit().data() );
		//	fprintf( f,"OpenGL renderer:      %s\n",rend.toLocal8Bit().data() );
		//	fprintf( f,"OpenGL Version:       %s\n",ver.toLocal8Bit().data() );
		//	if( OpenGL::supportMemoryQuery() )
		//		fprintf( f,"Total Graphic Memory: %d MB\n", OpenGL::glGetTotalMemory() >> 10);
		//	else
		//		fprintf( f,"Total Graphic Memory: Unknown\n");

		//	fprintf( f,"\n--------------------- Supported Extensions ---------------------\n\n");
		//	for(size_t i=0;i<OpenGL::glExtensions.size(); ++i)
		//		fprintf( f,"%s\n",OpenGL::glExtensions[i].c_str() );
		//	fclose(f);
		//}	
		return true;
	}
#endif

	return false;
}

//----------------------------------------------------------------------------------------------
void OpenGL::glCheckError(const char* file, unsigned line)
{
	GLenum err = glGetError();
	if( err != GL_NO_ERROR )
	{
		std::cout << "OpenGL ERROR [ " << err 
			      << " - "             << gluErrorString(err)
				  << " ]   (file "     << std::string(file)
				  << ", "              << line
				  << ")";
	}
}

//----------------------------------------------------------------------------------------------
bool OpenGL::glSupportMemoryQuery()
{
	static bool first   = true;
	static bool support = false;
	if(first)
	{
		//bool support = false;
		for(size_t i=0; i<glExtensions.size(); ++i)
			if( glExtensions[i] == std::string("GL_NVX_gpu_memory_info") )
			{
				support = true;
				break;
			}
		
		first = false;
	}
	
	return support;
}

//----------------------------------------------------------------------------------------------
// returns total dedicated memory in KB ( >> 10 to get MB)
int OpenGL::glGetDedicatedTotalMemory()
{
	GLint dedicatedMemKB = 0;
	
	if( glSupportMemoryQuery() )
		glGetIntegerv(GL_GPU_MEMORY_INFO_DEDICATED_VIDMEM_NVX, &dedicatedMemKB);
	return dedicatedMemKB;
}


//----------------------------------------------------------------------------------------------
// returns available free memory in KB ( >> 10 to get MB)
int OpenGL::glGetFreeMemory()
{
	GLint freeMemKB = 0;
	if( glSupportMemoryQuery() )
		glGetIntegerv(GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX, &freeMemKB);
	return freeMemKB;
}

//----------------------------------------------------------------------------------------------
// returns total available memory in KB ( >> 10 to get MB)
int OpenGL::glGetTotalMemory()
{
	GLint totalMemKB = 0;
	
	if( glSupportMemoryQuery() )
		glGetIntegerv(GL_GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX, &totalMemKB);	
	return totalMemKB;
}